import {_decorator, Animation, AnimationState, Material, MeshRenderer, Node, ParticleSystem, Vec3} from 'cc';
import {LaserEffect} from "db://assets/scripts/game/effect/monsterSkill/LaserEffect";
import {EventManager} from "db://assets/scripts/common/EventManager";
import {FireBallBigEffect} from "db://assets/scripts/game/effect/monsterSkill/FireBallBigEffect";
import {EventType} from "db://assets/scripts/common/EventType";
import {GameManager} from "db://assets/scripts/game/GameManager";
import {FireBallEffect} from "db://assets/scripts/game/effect/monsterSkill/FireBallEffect";
import {JetFiresEffect} from "db://assets/scripts/game/effect/monsterSkill/JetFiresEffect";
import {UIManager} from "db://assets/scripts/common/UIManager";
import {MonsterController} from "db://assets/scripts/game/role/monster/MonsterController";
import {MonsterSkillEnum} from "db://assets/scripts/game/role/monster/MonsterSkillEnum";
import {TornadoEffect} from "db://assets/scripts/game/effect/monsterSkill/TornadoEffect";
import {PoolManager} from "db://assets/scripts/common/PoolManager";
import {EffectManager} from "db://assets/scripts/common/EffectManager";
import {AudioManager} from "db://assets/scripts/common/AudioManager";
import {SkillField} from "db://assets/scripts/data/db/SkillField";
import {EnergyBallEffect} from "db://assets/scripts/game/effect/monsterSkill/EnergyBallEffect";
import {Utils} from "db://assets/scripts/utils/Utils";
import {ResourceUtils} from "db://assets/scripts/common/ResourceUtils";
import {AudioPaths} from "db://assets/scripts/common/AudioPaths";
import {DispersionSurroundEffect} from "db://assets/scripts/game/effect/monsterSkill/DispersionSurroundEffect";
import {DispersionEffect} from "db://assets/scripts/game/effect/monsterSkill/DispersionEffect";

const {ccclass, property} = _decorator;

/**
 * Boss脚本
 */
@ccclass('BossController')
export class BossController extends MonsterController {
    /**
     * 龙头
     */
    @property(Node)
    public ndSocketDragonHead: Node;
    /**
     * 大龙默认材质
     */
    @property(Material)
    public matDragon: Material;
    /**
     * 大龙受击后材质变白
     */
    @property(Material)
    public matDragonHit: Material;
    /**
     * 大龙网格
     */
    @property(MeshRenderer)
    public meshDragon: MeshRenderer;

    /**
     * 闪白倒计时
     */
    private countdown: number = 0.2;
    /**
     * 技能默认角度
     */
    private originSkillEuler: Vec3 = new Vec3();
    /**
     * 是否正在释放技能
     */
    private skillReleasing: boolean = false;

    lateUpdate(deltaTime: number) {
        if (this.countdown > 0 && !this.isDie) {
            this.countdown -= deltaTime;

            if (this.countdown <= 0) {
                this.meshDragon?.setMaterial(this.matDragon, 0);
            }
        }
    }

    public init(baseInfo: any, layerInfo: any) {
        super.init(baseInfo, layerInfo);

        this.bloodTipOffsetPosition.set(0, 50, 0);
        this.hitEffectPosition.set(0, 0.04, 0);
        this.skillReleasing = false;
        this.countdown = 0.2;
        this.meshDragon?.setMaterial(this.matDragon, 0);
    }

    public refreshBlood(bloodNum: number, tipType: number) {
        EventManager.dispatchEvent(EventType.REFRESH_BOSS_BLOOD, bloodNum);
        UIManager.getInstance().showBloodTip(this, tipType, bloodNum, this.bloodTipOffsetPosition);
    }

    public playAttackAnimation() {
        super.playAttackAnimation();

        this.skillReleasing = false;
    }

    /**
     * 向玩家释放技能
     *
     * @param {boolean} [isNormalAttack=false] 是否是普通攻击、反之喷火
     * @return {*}
     * @memberof Boss
     */
    public releaseSkillToPlayer(isNormalAttack: boolean = false) {
        if (this.skillReleasing) {
            return;
        }

        //boss是非近战的怪物，必须带技能，这里做个容错
        if (!this.allSkillInfo.length) {
            let offsetLength = Utils.getTwoNodeXZLength(this.node, GameManager.getInstance().gamePlayerProxy.getPlayerNode());
            if (offsetLength <= this.minLength * this.minLengthRatio) {
                GameManager.getInstance().gamePlayerProxy.getPlayerController().reduceBlood(this.baseInfo);
            }
            return;
        }

        if (isNormalAttack && this.skill[SkillField.ID] !== MonsterSkillEnum.JET_FIRES) {
            this.skillReleasing = true;

            ResourceUtils.loadEffect(`${this.skill.resourceName}/${this.skill.resourceName}`).then((prefab: any) => {
                if (this.moving) {
                    return;
                }

                let ndMonsterSkill = PoolManager.getInstance().getNode(prefab, GameManager.getInstance().node);
                ndMonsterSkill.setWorldPosition(this.node.worldPosition.x, 2.5, this.node.worldPosition.z);
                ndMonsterSkill.forward = this.attackForward.negative();

                let scriptSkillCollider: any = null!;
                //怪物技能初始化
                switch (this.skill.id) {
                    case MonsterSkillEnum.ENERGY_BALL:
                        ndMonsterSkill.setWorldPosition(this.ndSocketDragonHead.worldPosition.x, 2.5, this.ndSocketDragonHead.worldPosition.z);
                        scriptSkillCollider = ndMonsterSkill.getComponent(EnergyBallEffect);
                        scriptSkillCollider.init(this.skill, this.baseInfo, this);
                        break;
                    case MonsterSkillEnum.FIRE_BALL:
                        ndMonsterSkill.setWorldPosition(this.ndSocketDragonHead.worldPosition);
                        scriptSkillCollider = ndMonsterSkill.getComponent(FireBallEffect);
                        scriptSkillCollider.init(this.skill, this.baseInfo, this);
                        break;
                    case MonsterSkillEnum.DISPERSION:
                        ndMonsterSkill.children.forEach((ndChild: Node, idx: number) => {
                            let scriptSkillCollider = ndChild.getComponent(DispersionEffect);
                            scriptSkillCollider.init(this.skill, this.baseInfo);
                        })
                        break;
                    case MonsterSkillEnum.TORNADO:
                        ndMonsterSkill.setWorldPosition(this.ndSocketDragonHead.worldPosition);
                        scriptSkillCollider = ndMonsterSkill.getComponent(TornadoEffect);
                        scriptSkillCollider.init(this.skill, this.baseInfo, this);
                        break;
                    case MonsterSkillEnum.FIRE_BALL_BIG:
                        scriptSkillCollider = ndMonsterSkill.getComponent(FireBallBigEffect);
                        scriptSkillCollider.init(this.skill, this.baseInfo, this);
                        break;
                    case MonsterSkillEnum.DISPERSION_SURROUND:
                        ndMonsterSkill.children.forEach((ndChild: Node) => {
                            let scriptSkillCollider = ndChild.getComponent(DispersionSurroundEffect);
                            scriptSkillCollider.init(this.skill, this.baseInfo);
                        })
                        break;
                    case MonsterSkillEnum.LASER:
                        ndMonsterSkill.setWorldPosition(this.ndSocketDragonHead.worldPosition);
                        scriptSkillCollider = ndMonsterSkill.getComponent(LaserEffect);
                        scriptSkillCollider.init(this.skill, this.baseInfo, this);
                        break;
                }

                this.refreshSkill();
            })
        } else if (!isNormalAttack && this.skill.id === MonsterSkillEnum.JET_FIRES) {
            this.skillReleasing = true;

            ResourceUtils.loadEffect(`${this.skill.resourceName}/${this.skill.resourceName}`).then((prefab: any) => {
                if (this.moving) {
                    return;
                }

                let monsterSkillNode = PoolManager.getInstance().getNode(prefab, this.ndSocketDragonHead);
                monsterSkillNode.eulerAngles = this.originSkillEuler;

                let ndChild = monsterSkillNode.getChildByName("boxCollider");
                ndChild.active = true;

                let script = monsterSkillNode.getComponent(JetFiresEffect);
                EffectManager.getInstance().playParticle(monsterSkillNode);

                script.init(this.skill, this.baseInfo, this);

                AudioManager.getInstance().playSound(AudioPaths.jetFireSound);

                let arrParticle: ParticleSystem[] = monsterSkillNode.getComponentsInChildren(ParticleSystem);
                arrParticle.forEach((element: ParticleSystem) => {
                    element.simulationSpeed = 1;
                    element?.clear();
                    element?.stop();
                    element?.play();
                })

                //播放触发器动画
                let aniCom = monsterSkillNode.getComponent(Animation);
                let aniState: AnimationState;
                let aniName = aniCom.defaultClip?.name;
                if (aniName) {
                    aniCom.getState(aniName).time = 0;
                    aniCom.getState(aniName).sample();
                    aniCom.play();

                    aniState = aniCom.getState(aniName);
                    aniState.speed = GameManager.getInstance().gameSpeedProxy.getGameSpeed();
                }

                aniCom.once(Animation.EventType.FINISHED, () => {
                    ndChild.active = false;
                })

                this.warningScript?.hideWarning();

                setTimeout(() => {
                    PoolManager.getInstance().putNode(monsterSkillNode);
                }, 4000)

                this.refreshSkill();
            })
        }
    }

    /**
     * 大龙受击打后闪白效果
     */
    public changeDragonMat() {
        if (this.countdown <= 0) {
            this.meshDragon?.setMaterial(this.matDragonHit, 0);
            this.countdown = 0.2;
        }
    }
}

